// dama_server

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <signal.h>
#include <errno.h>
#include <string.h>

#include "dama_data.h"
#include "dama_logic.h"
#include "server_network.h"

int even(int n);

void createBoard(match_t *m);
void playerMoves(match_t *m, int direction);
void runMatch(match_t *m);
match_t *create_match(int player1_socket, int player2_socket);

int main()
{
	int listener, plsock1, plsock2;
	struct sockaddr_in client1, client2;
	
	listener = create_socket();
	
    listen(listener, 2);
    
    printf("Server avviato\n");
    
    while(1){
		// Gestione delle connessioni dei client
		socklen_t client_len = sizeof(client1);
		
		if ((plsock1 = accept(listener, (struct sockaddr *)&client1,
                              &client_len)) < 0) {
			perror(strerror(errno));
			exit(3);
		}
        
		if ((plsock2 = accept(listener, (struct sockaddr *)&client2,
                              &client_len)) < 0) {
			perror(strerror(errno));
			exit(3);
		}

        printf("Sono arrivati due client\n");
        
        match_t *m = create_match(plsock1, plsock2);
        
        runMatch(m);

	} //end while
}

// Creo la plancia di gioco
void createBoard(match_t *m)
{	

	int q;
	for(int j=0; j<=2; j++){
		for(int i=0; i<8; i++)
		{
			q=i+j;
			if(even(q) == 1)
			{
				m->board[j][i]='w';
				m->wpieces++;
			}else{
				m->board[j][i]='e';
			}
		}
	}
	
	for(int j=3; j<=4; j++){
		for(int i=0; i<8; i++)
		{
			m->board[j][i]='e';
		}
	}
	
	for(int j=5; j<=7; j++){
		for(int i=0; i<8; i++)
		{
			q=i+j;
			if(even(q) == 1)
			{
				m->board[j][i]='b';
				m->bpieces++;
			}else{
				m->board[j][i]='e';
			}
		}
	}
}

// Gestisco l'arrivo della proposta, la valutazione e
// l'aggiornamento dei client
void playerMoves(match_t *m, int direction)
{
	printf("MOSSA--------------------\n");
	printf("direction: %i\n", direction);
	
	int sock1, sock2;
	char player1, player2;
	move_message_t *proposal = malloc(sizeof(move_message_t));
	int validMove = 1;
	
	//se la direzione è 0 gioca bianco, altrimenti nero
	if(direction==0)
	{
		sock1=m->fplayer1;
		sock2=m->fplayer2;
		player1='w';
		player2='b';
	}else// if(direction==1)
	{
		sock1=m->fplayer2;
		sock2=m->fplayer1;
		player1='b';
		player2='w';
	}
	sendControlMessage(sock1, 0);
	sendControlMessage(sock2, 3);
		
	// Ricezione ed analisi della proposta di movimento
	while(validMove != 0)
	{	
		recvMoveProposal(sock1, proposal);
		printf("ho ricevuto la proposal.\n");
		validMove = evaluateProposal(proposal, m);
		printf("Ho valutato la proposal.\n");
		
		// Valuto se è una mossa consentita
		// Cambio la flag se devo segnalare la vittoria
		// e mando un messaggio di controllo al player
		// giocante
		// Se c'è ancora da mangiare, continuo e lo segnalo
		if(validMove == 0)
		{
			switch(m->state){
				case WhiteWin:
					sendControlMessage(sock1, 5);
					break;
				case BlackWin:
					sendControlMessage(sock1, 6);
					break;
				default:
					printf("proposal flag:%i\n", proposal->flag);
					if(proposal->flag == 1){
						validMove = 3;
						sendControlMessage(sock1, 0);
					}else{
						sendControlMessage(sock1, 3);
					}
					m->lastmoveX = proposal->endX;
					m->lastmoveY = proposal->endY;
					break;
			}
			
			// Dico al client 2 di aggiornare la board
			sendNextMove(sock2, proposal);
			printf("Invio mossa a waiting player\n");
		}else if(validMove == 1){
		// La mossa non è valida
			sendControlMessage(sock1, 1);
		}else if(validMove == 2){
		// Segnalo che bisogna mangiare
			sendControlMessage(sock1, 2);
			// sendControlMessage(sock1, proposal->flag);
		}
	}
}

// Esecuzione della partita
void runMatch(match_t *m)
{
	// Se muove il bianco la direzione è 0, se muove il nero è 1
	int direction = 0;
	
	while(m->state == InProgress)
	{
		playerMoves(m, direction);
		printf("giocatore designato ha mosso\n");
		(direction == 0)? (direction = 1): (direction = 0);
	}
	
	// Se qualcuno ha vinto, segnala ai client il vincitore
	switch(m->state)
	{
	case WhiteWin:
		sendControlMessage(m->fplayer1, 5);
		sendControlMessage(m->fplayer2, 5);
		printf("vince bianco e l'ho segnalato\n");
		break;
	case BlackWin:
		sendControlMessage(m->fplayer1, 6);
		sendControlMessage(m->fplayer2, 6);
		printf("vince nero e l'ho segnalato\n");
		break;
	case InProgress:
		break;
	case Disconnect:
		printf("Client disconnesso.\n");
		exit(0);
	}
}

// Creo la partita
match_t *create_match(int player1_socket, int player2_socket)
{
	match_t *m = malloc(sizeof(match_t));
	printf("creato match\n");
	m->wpieces = m->bpieces = 0;
	
	createBoard(m);
	m->lastmoveX = 0;
	m->lastmoveY = 0;
	
	m->fplayer1 = player1_socket;
	m->fplayer2 = player2_socket;
	m->state = InProgress;
	printf("m inizializzato\n");
	
	sendControlMessage(player1_socket, 3);
	printf("tu sei bianchi\n");
	sendControlMessage(player2_socket, 4);
	printf("tu sei neri\n");
		
	return m;		
}
